package zconfig

import (
	"github.com/pkg/errors"
	"gopkg.in/ini.v1"
	"strconv"
	"strings"
)

type ConfigReader struct {
	configReader *ini.File
}

var NotInitError = errors.New("config not init")

func LoadConfig(configFile string) (*ConfigReader, error) {
	var c ConfigReader
	conf, err := ini.Load(configFile)
	if err != nil {
		c.configReader = nil
		return nil, errors.Wrap(err, "Load config error")
	}
	c.configReader = conf
	return &c, nil
}

func (c *ConfigReader) GetString(section, key string) string {
	if c.configReader == nil {
		return ""
	}
	return c.configReader.Section(section).Key(key).String()
}

func (c *ConfigReader) GetInt32(section, key string) int32 {
	if c.configReader == nil {
		return 0
	}
	res, _ := c.configReader.Section(section).Key(key).Int()
	return int32(res)
}

func (c *ConfigReader) GetInt64(section, key string) int64 {
	if c.configReader == nil {
		return 0
	}
	res, _ := c.configReader.Section(section).Key(key).Int64()
	return res
}

func (c *ConfigReader) GetFloat64(section, key string) float64 {
	if c.configReader == nil {
		return 0
	}
	res, _ := c.configReader.Section(section).Key(key).Float64()
	return res
}

func (c *ConfigReader) GetBool(section, key string) bool {
	if c.configReader == nil {
		return false
	}
	res, _ := c.configReader.Section(section).Key(key).Bool()
	return res
}

func (c *ConfigReader) GetStringList(section, key, sep string) []string {
	result := c.GetString(section, key)
	return strings.Split(result, sep)
}

func (c *ConfigReader) GetInt64List(section, key, sep string) []int64 {
	var result []int64
	fields := c.GetStringList(section, key, sep)
	for _, item := range fields {
		res, err := strconv.ParseInt(item, 0, 64)
		if err != nil {
			continue
		}
		result = append(result, res)
	}
	return result
}

func (c *ConfigReader) GetFloat64List(section, key, sep string) []float64 {
	var result []float64
	fields := c.GetStringList(section, key, sep)
	for _, item := range fields {
		res, err := strconv.ParseFloat(item, 64)
		if err != nil {
			continue
		}
		result = append(result, res)
	}
	return result
}

func (c *ConfigReader) GetConfig() *ini.File {
	return c.configReader
}

func (c *ConfigReader) Unmarshal(v interface{}) error {
	if c.configReader == nil {
		return NotInitError
	}
	err := c.configReader.MapTo(v)
	return err
}

func (c *ConfigReader) UnmarshalWithSection(section string, v interface{}) error {
	if c.configReader == nil {
		return NotInitError
	}
	return c.configReader.Section(section).MapTo(v)
}
